package com.ingenico.insider.services.impl;

import java.text.MessageFormat;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.logging.Logger;

import javax.swing.Icon;
import javax.swing.JOptionPane;

import com.ingenico.insider.util.Constants;

public final class MessageBoxSupplier {
	private static Logger _logger = Logger.getLogger(MessageBoxSupplier.class.getCanonicalName());

	/**
	 * The resource bundle that contains all the resources
	 */
	private static final ResourceBundle resourceBundle = ResourceBundle.getBundle(MessageBoxSupplier.class.getSimpleName());

	/**
	 * Public constant keywords
	 */
	public static final String SEPARATOR = Constants.SEPARATOR;

	public static final String TITLE_KEY = LocalisationSupplier.TITLE_KEY;
	public static final String DEFAULT_KEY = "default";
	public static final String MESSAGE_KEY = "message";
	public static final String GENERAL_ERROR_KEY = "general_error";
	
	public static final String DIALOG_PATH = Constants.INSIDER_BASE + Constants.SEPARATOR + "dialog";
	public static final String ERROR_PATH = DIALOG_PATH + Constants.SEPARATOR + "error";
	public static final String CONFIRM_PATH = DIALOG_PATH + Constants.SEPARATOR + "confirm";


	/**
	 * singleton instance
	 */
	private static MessageBoxSupplier instance;

	private final String defaultErrorTitle;
	private final String defaultErrorMessage;

	/**
	 * private constructor of final class to prevent external instantiation
	 */
	private MessageBoxSupplier() {
		final String baseKey = ERROR_PATH + SEPARATOR + DEFAULT_KEY;
		String resourceKey;
		String resourceValue;
		String message;

		resourceValue = null;
		resourceKey = baseKey + SEPARATOR + TITLE_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.fine("Setting Default Error Title: " + resourceKey + " = " + resourceValue);
			} else {
				_logger.warning("Resource Key empty (" + resourceKey + "). Default Error Title empty");
			}
		} catch (MissingResourceException mre) {
			message = "Resource Key Missing (" + resourceKey + "). Default Error Title not set";
			_logger.severe(message);
			resourceValue = message;
		}
		defaultErrorTitle = resourceValue;

		resourceValue = null;
		resourceKey = baseKey + SEPARATOR + MESSAGE_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.fine("Setting Default Error Message: " + resourceKey + " = " + resourceValue);
			} else {
				_logger.warning("Resource Key empty (" + resourceKey + "). Default Error Message empty");
			}
		} catch (MissingResourceException mre) {
			message = "Resource Key Missing (" + resourceKey + "). Default Error Message not set";
			_logger.severe(message);
			resourceValue = message;
		}
		defaultErrorMessage = resourceValue;
	}

	private String getMessageTitle(final String baseKey) {
		final String resourceKey = baseKey + SEPARATOR + TITLE_KEY;
		try {
			final String resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.fine("Setting Title: " + resourceKey + " = " + resourceValue);
				return resourceValue;
			} else {
				_logger.fine("Resource Key empty (" + resourceKey + "). Message title not set, using default (" + defaultErrorTitle + ")");
				return defaultErrorTitle;
			}
		} catch (MissingResourceException mre) {
			_logger.fine("Resource Key Missing (" + resourceKey + "). Message title not set, using default (" + defaultErrorTitle + ")");
			return defaultErrorTitle;
		}
	}

	private String getMessageText(final String baseKey, final Object ... args) {
		final String resourceKey = baseKey + SEPARATOR + MESSAGE_KEY;
		try {
			final String resourceValue = resourceBundle.getString(resourceKey);
			if (resourceValue.isEmpty()) {
				_logger.fine("Resource Key empty (" + resourceKey + "). Message not set, using default (" + defaultErrorTitle + ")");
				return resourceValue;
			} else if (args.length > 0){
				final String message = MessageFormat.format(resourceValue, args); 
				_logger.fine("Setting Formatted Message: " + resourceKey + " = " + message);
				return message;
			} else {
				_logger.fine("Setting Message: " + resourceKey + " = " + resourceValue);
				return resourceValue;
			}
		} catch (MissingResourceException mre) {
			// We need a message to display !
			_logger.severe("Resource Key Missing (" + resourceKey + "). Message text defaults to describing the generic error.");
			return MessageFormat.format(defaultErrorMessage, mre);
		}
	}

	/**
	 * retrieve the singleton instance
	 *
	 * @return the MessageBoxSupplier singleton
	 */
	public static MessageBoxSupplier getInstance() {
		if (instance == null) {
			_logger.info(MessageBoxSupplier.class.getName() + " instance does not exist... Creating instance.");
			instance = new MessageBoxSupplier();
		}
		return instance;
	}

	public void showErrorDialog(String key, Object ... arguments) {
		final String baseKey = ERROR_PATH + SEPARATOR + key;
		final String title = getMessageTitle(baseKey);
		final String message = getMessageText(baseKey, arguments);

		// Finally display the dialog
		JOptionPane.showMessageDialog(
			DockableViewsSupplier.getInstance().getComponent(),
			message,
			title,
			JOptionPane.ERROR_MESSAGE
		);
	}

	public int showConfirmDialog(String key, Object ... arguments) {
		final String baseKey = CONFIRM_PATH + Constants.SEPARATOR + key;
		final String title = getMessageTitle(baseKey);
		final String message = getMessageText(baseKey, arguments);

		// Finally display the dialog
		return JOptionPane.showConfirmDialog(
			DockableViewsSupplier.getInstance().getComponent(),
			message,
			title,
			JOptionPane.YES_NO_CANCEL_OPTION
		);
	}

	public int showOptionDialog (Object message, String title, int optionType, int messageType, Icon icon, Object[] options, Object initialValue) {
		return JOptionPane.showOptionDialog(
			DockableViewsSupplier.getInstance().getComponent(),
			message,
			title,
			optionType,
			messageType,
			icon,
			options,
			initialValue
		);				
	}
}
